package com.iogogogo.supervisord.core;

import com.iogogogo.supervisord.domain.SupervisordProcess;
import com.iogogogo.supervisord.exception.SupervisordException;
import com.iogogogo.supervisord.properties.SupervisordProperties;
import io.vavr.Tuple;
import io.vavr.Tuple2;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * The interface Supervisord.
 */
public interface Supervisord extends Constant {

    //-------------------System Methods------------------------//

    /**
     * List methods list.
     *
     * @return the list
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    List<String> listMethods() throws IOException, SupervisordException;

    /**
     * Method help string.
     *
     * @param method the method
     * @return the string
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String methodHelp(String method) throws IOException, SupervisordException;

    /**
     * Method signature object.
     *
     * @param name the name
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object methodSignature(String name) throws IOException, SupervisordException;

    /**
     * Multicall object.
     *
     * @param calls the calls
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object multicall(Map<String, Object> calls) throws IOException, SupervisordException;
    //-------------------System Methods------------------------//


    //-------------------Status and Control------------------------//

    /**
     * Gets api version.
     *
     * @return the api version
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String getAPIVersion() throws IOException, SupervisordException;

    /**
     * Gets supervisor version.
     *
     * @return the supervisor version
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String getSupervisorVersion() throws IOException, SupervisordException;

    /**
     * Gets identification.
     *
     * @return the identification
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String getIdentification() throws IOException, SupervisordException;

    /**
     * Gets state.
     *
     * @return the state
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Map<String, Object> getState() throws IOException, SupervisordException;

    /**
     * Gets pid.
     *
     * @return the pid
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Integer getPID() throws IOException, SupervisordException;

    /**
     * Read log string.
     *
     * @param offset the offset
     * @param length the length
     * @return the string
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String readLog(int offset, int length) throws IOException, SupervisordException;

    /**
     * Clear log boolean.
     *
     * @return the boolean
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Boolean clearLog() throws IOException, SupervisordException;

    /**
     * Shutdown object.
     *
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object shutdown() throws IOException, SupervisordException;

    /**
     * Restart boolean.
     *
     * @return the boolean
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Boolean restart() throws IOException, SupervisordException;
    //-------------------Status and Control------------------------//


    //-------------------Process Control------------------------//

    /**
     * Gets process info.
     *
     * @param name the name
     * @return the process info
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    SupervisordProcess getProcessInfo(String name) throws IOException, SupervisordException;

    /**
     * Gets all process info.
     *
     * @return the all process info
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    List<SupervisordProcess> getAllProcessInfo() throws IOException, SupervisordException;

    /**
     * Start process boolean.
     *
     * @param name the name
     * @param wait the wait
     * @return the boolean
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Boolean startProcess(String name, boolean wait) throws IOException, SupervisordException;

    /**
     * Start all processes list.
     *
     * @param wait the wait
     * @return the list
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    List<SupervisordProcess> startAllProcesses(boolean wait) throws IOException, SupervisordException;

    /**
     * Start process group list.
     *
     * @param name the name
     * @param wait the wait
     * @return the list
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    List<SupervisordProcess> startProcessGroup(String name, boolean wait) throws IOException, SupervisordException;

    /**
     * Stop process boolean.
     *
     * @param name the name
     * @param wait the wait
     * @return the boolean
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Boolean stopProcess(String name, boolean wait) throws IOException, SupervisordException;

    /**
     * Stop process group list.
     *
     * @param name the name
     * @param wait the wait
     * @return the list
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    List<SupervisordProcess> stopProcessGroup(String name, boolean wait) throws IOException, SupervisordException;

    /**
     * Stop all processes list.
     *
     * @param wait the wait
     * @return the list
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    List<SupervisordProcess> stopAllProcesses(boolean wait) throws IOException, SupervisordException;

    /**
     * Signal process object.
     *
     * @param name   the name
     * @param signal the signal
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object signalProcess(String name, int signal) throws IOException, SupervisordException;

    /**
     * Signal process group object.
     *
     * @param name   the name
     * @param signal the signal
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object signalProcessGroup(String name, int signal) throws IOException, SupervisordException;

    /**
     * Signal all processes object.
     *
     * @param signal the signal
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object signalAllProcesses(int signal) throws IOException, SupervisordException;

    /**
     * Send process stdin object.
     *
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object sendProcessStdin() throws IOException, SupervisordException;

    /**
     * Send remote comm event object.
     *
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object sendRemoteCommEvent() throws IOException, SupervisordException;

    /**
     * Reload config object.
     *
     * @return the object
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Object reloadConfig() throws IOException, SupervisordException;

    /**
     * Add process group boolean.
     *
     * @param name the name
     * @return the boolean
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Boolean addProcessGroup(String name) throws IOException, SupervisordException;

    /**
     * Remove process group boolean.
     *
     * @param name the name
     * @return the boolean
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Boolean removeProcessGroup(String name) throws IOException, SupervisordException;
    //-------------------Process Control------------------------//


    //-------------------Process Logging------------------------//

    /**
     * Read process stdout log string.
     *
     * @param name   the name
     * @param offset the offset
     * @param length the length
     * @return the string
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String readProcessStdoutLog(String name, long offset, long length) throws IOException, SupervisordException;

    /**
     * Read process stderr log string.
     *
     * @param name   the name
     * @param offset the offset
     * @param length the length
     * @return the string
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String readProcessStderrLog(String name, long offset, long length) throws IOException, SupervisordException;


    /**
     * Tail process stdout log string.
     *
     * @param name   the name
     * @param offset the offset
     * @param length the length
     * @return the string
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String tailProcessStdoutLog(String name, long offset, long length) throws IOException, SupervisordException;

    /**
     * Tail process stderr log string.
     *
     * @param name   the name
     * @param offset the offset
     * @param length the length
     * @return the string
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    String tailProcessStderrLog(String name, long offset, long length) throws IOException, SupervisordException;

    /**
     * Clear process logs boolean.
     *
     * @param name the name
     * @return the boolean
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    Boolean clearProcessLogs(String name) throws IOException, SupervisordException;

    /**
     * Clear all process logs list.
     *
     * @return the list
     * @throws IOException          the io exception
     * @throws SupervisordException the supervisord exception
     */
    List<SupervisordProcess> clearAllProcessLogs() throws IOException, SupervisordException;
    //-------------------Process Logging------------------------//


    /**
     * Gets supervisord properties.
     *
     * @return the supervisord properties
     */
    SupervisordProperties getSupervisordProperties();

    /**
     * Build full param string.
     *
     * @param method the method
     * @return the string
     */
    default String buildFullParam(final String method) {
        return String.join("", DEFAULT_NAMESPACE, DOT, method);
    }

    /**
     * Build param tuple 2.
     *
     * @param method the method
     * @param params the params
     * @return the tuple 2
     */
    default Tuple2<String, String> buildParam(String method, Object... params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\"?>\n")
                .append(METHOD_CALL_S)
                .append(METHOD_NAME_S).append(method).append(METHOD_NAME_E);
        if (params != null && params.length > 0) {
            sb.append(PARAMS_S);
            for (Object arg : params) {
                sb.append(PARAM_S).append(VALUE_S);
                if (arg instanceof Integer) {
                    sb.append(INT_S).append(arg).append(INT_E);
                } else {
                    sb.append(STRING_S).append(arg).append(STRING_E);
                }
                sb.append(VALUE_E).append(PARAM_E);
            }
            sb.append(PARAMS_E);
        }
        sb.append(METHOD_CALL_E);

        return Tuple.of(method, sb.toString());
    }
}
